home *** CD-ROM | disk | FTP | other *** search
- #ifndef lintuse free() insteSid = "$Id: plot.c,v 1.18.2.2 1999/09/23 13:26:36 lhecking Exp $";
- #endif
-
- /* GNUPLOT - plot.c */
-
- /*[
- * Copyright 1986 - 1993, 1998 Thomas Williams, Colin Kelley
- *
- * Permission to use, copy, and distribute this software and its
- * documentation for any purpose with or without fee is hereby granted,
- * provided that the above copyright notice appear in all copies and
- * that both that copyright notice and this permission notice appear
- * in supporting documentation.
- *
- * Permission to modify the software is granted, but not the right to
- * distribute the complete modified source code. Modifications are to
- * be distributed as patches to the released version. Permission to
- * distribute binaries produced by compiling modified sources is granted,
- * provided you
- * 1. distribute the corresponding source modifications from the
- * released version in the form of a patch file along with the binaries,
- * 2. add special version identification to distinguish your version
- * in addition to the base release version number,
- * 3. provide your name and address as the primary contact for the
- * support of your modified version, and
- * 4. retain our contact information in regard to use of the base
- * software.
- * Permission to distribute the released version of the source code along
- * with corresponding source modifications in the form of a patch file is
- * granted with same provisions 2 through 4 for binary distributions.
- *
- * This software is provided "as is" without express or implied warranty
- * to the extent permitted by applicable law.
- ]*/
-
- #include <signal.h>
-
- #include "plot.h"
- #include "fit.h"
- #include "setshow.h"
- #include "fnproto.h"
- #include <setjmp.h>
-
- #if defined(MSDOS) || defined(DOS386) || defined(__EMX__)
- # include <io.h>
- #endif
-
- /* HBB: for the control87 function, if used with DJGPP V1: */
- #if defined(DJGPP) && (DJGPP!=2)
- # include "ctrl87.h"
- #endif
-
- #ifdef VMS
- # ifndef __GNUC__
- # include <unixio.h>
- # endif
- # include <smgdef.h>
- extern int vms_vkid;
- extern smg$create_virtual_keyboard();
- extern int vms_ktid;
- extern smg$create_key_table();
- #endif /* VMS */
-
- #ifdef AMIGA_SC_6_1
- # include <proto/dos.h>
- #endif
-
- #ifdef _Windows
- # include <windows.h>
- # ifndef SIGINT
- # define SIGINT 2 /* for MSC */
- # endif
- #endif /* _Windows */
-
- extern FILE *gpoutfile;
-
- TBOOLEAN interactive = TRUE; /* FALSE if stdin not a terminal */
- TBOOLEAN noinputfiles = TRUE; /* FALSE if there are script files */
-
- /* these 2 could be in misc.c, but are here with all the other globals */
- TBOOLEAN do_load_arg_substitution = FALSE;
- char *call_args[10] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
-
- char *infile_name = NULL; /* name of command file; NULL if terminal */
-
- #ifdef HAVE_LIBREADLINE
- extern char *rl_readline_name;
- extern int rl_complete_with_tilde_expansion;
- #endif
-
- #ifdef X11
- extern int X11_args __PROTO((int, char **));
- #endif
-
- /* patch to get home dir, see command.c */
- #if (defined (__TURBOC__) && (defined (MSDOS) || defined(DOS386))) || defined(DJGPP)
- # include <dir.h> /* MAXPATH */
- char HelpFile[MAXPATH];
- #endif /* - DJL */
-
- #ifndef STDOUT
- # define STDOUT 1
- #endif
-
- /* a longjmp buffer to get back to the command line */
- #ifdef _Windows
- static jmp_buf far command_line_env;
- #else
- static jmp_buf command_line_env;
- #endif
-
- static void load_rcfile __PROTO((void));
- RETSIGTYPE inter __PROTO((int anint));
-
- /* built-in function table */
- struct ft_entry GPFAR ft[] =
- {
- /* internal functions: */
- {"push", (FUNC_PTR) f_push},
- {"pushc", (FUNC_PTR) f_pushc},
- {"pushd1", (FUNC_PTR) f_pushd1},
- {"pushd2", (FUNC_PTR) f_pushd2},
- {"pushd", (FUNC_PTR) f_pushd},
- {"call", (FUNC_PTR) f_call},
- {"calln", (FUNC_PTR) f_calln},
- {"lnot", (FUNC_PTR) f_lnot},
- {"bnot", (FUNC_PTR) f_bnot},
- {"uminus", (FUNC_PTR) f_uminus},
- {"lor", (FUNC_PTR) f_lor},
- {"land", (FUNC_PTR) f_land},
- {"bor", (FUNC_PTR) f_bor},
- {"xor", (FUNC_PTR) f_xor},
- {"band", (FUNC_PTR) f_band},
- {"eq", (FUNC_PTR) f_eq},
- {"ne", (FUNC_PTR) f_ne},
- {"gt", (FUNC_PTR) f_gt},
- {"lt", (FUNC_PTR) f_lt},
- {"ge", (FUNC_PTR) f_ge},
- {"le", (FUNC_PTR) f_le},
- {"plus", (FUNC_PTR) f_plus},
- {"minus", (FUNC_PTR) f_minus},
- {"mult", (FUNC_PTR) f_mult},
- {"div", (FUNC_PTR) f_div},
- {"mod", (FUNC_PTR) f_mod},
- {"power", (FUNC_PTR) f_power},
- {"factorial", (FUNC_PTR) f_factorial},
- {"bool", (FUNC_PTR) f_bool},
- {"dollars", (FUNC_PTR) f_dollars}, /* for using extension */
- {"jump", (FUNC_PTR) f_jump},
- {"jumpz", (FUNC_PTR) f_jumpz},
- {"jumpnz", (FUNC_PTR) f_jumpnz},
- {"jtern", (FUNC_PTR) f_jtern},
-
- /* standard functions: */
- {"real", (FUNC_PTR) f_real},
- {"imag", (FUNC_PTR) f_imag},
- {"arg", (FUNC_PTR) f_arg},
- {"conjg", (FUNC_PTR) f_conjg},
- {"sin", (FUNC_PTR) f_sin},
- {"cos", (FUNC_PTR) f_cos},
- {"tan", (FUNC_PTR) f_tan},
- {"asin", (FUNC_PTR) f_asin},
- {"acos", (FUNC_PTR) f_acos},
- {"atan", (FUNC_PTR) f_atan},
- {"atan2", (FUNC_PTR) f_atan2},
- {"sinh", (FUNC_PTR) f_sinh},
- {"cosh", (FUNC_PTR) f_cosh},
- {"tanh", (FUNC_PTR) f_tanh},
- {"int", (FUNC_PTR) f_int},
- {"abs", (FUNC_PTR) f_abs},
- {"sgn", (FUNC_PTR) f_sgn},
- {"sqrt", (FUNC_PTR) f_sqrt},
- {"exp", (FUNC_PTR) f_exp},
- {"log10", (FUNC_PTR) f_log10},
- {"log", (FUNC_PTR) f_log},
- {"besj0", (FUNC_PTR) f_besj0},
- {"besj1", (FUNC_PTR) f_besj1},
- {"besy0", (FUNC_PTR) f_besy0},
- {"besy1", (FUNC_PTR) f_besy1},
- {"erf", (FUNC_PTR) f_erf},
- {"erfc", (FUNC_PTR) f_erfc},
- {"gamma", (FUNC_PTR) f_gamma},
- {"lgamma", (FUNC_PTR) f_lgamma},
- {"ibeta", (FUNC_PTR) f_ibeta},
- {"igamma", (FUNC_PTR) f_igamma},
- {"rand", (FUNC_PTR) f_rand},
- {"floor", (FUNC_PTR) f_floor},
- {"ceil", (FUNC_PTR) f_ceil},
-
- {"norm", (FUNC_PTR) f_normal}, /* XXX-JG */
- {"inverf", (FUNC_PTR) f_inverse_erf}, /* XXX-JG */
- {"invnorm", (FUNC_PTR) f_inverse_normal}, /* XXX-JG */
- {"asinh", (FUNC_PTR) f_asinh},
- {"acosh", (FUNC_PTR) f_acosh},
- {"atanh", (FUNC_PTR) f_atanh},
-
- {"column", (FUNC_PTR) f_column}, /* for using */
- {"valid", (FUNC_PTR) f_valid}, /* for using */
- {"timecolumn", (FUNC_PTR) f_timecolumn}, /* for using */
-
- {"tm_sec", (FUNC_PTR) f_tmsec}, /* for timeseries */
- {"tm_min", (FUNC_PTR) f_tmmin}, /* for timeseries */
- {"tm_hour", (FUNC_PTR) f_tmhour}, /* for timeseries */
- {"tm_mday", (FUNC_PTR) f_tmmday}, /* for timeseries */
- {"tm_mon", (FUNC_PTR) f_tmmon}, /* for timeseries */
- {"tm_year", (FUNC_PTR) f_tmyear}, /* for timeseries */
- {"tm_wday", (FUNC_PTR) f_tmwday}, /* for timeseries */
- {"tm_yday", (FUNC_PTR) f_tmyday}, /* for timeseries */
-
- {NULL, NULL}
- };
-
- static struct udvt_entry udv_pi = { NULL, "pi", FALSE };
- /* first in linked list */
- struct udvt_entry *first_udv = &udv_pi;
- struct udft_entry *first_udf = NULL;
-
- static int exit_status = EXIT_SUCCESS;
-
- #ifdef OS2
- # define INCL_DOS
- # define INCL_REXXSAA
- # include <os2.h>
- # include <process.h>
- ULONG RexxInterface(PRXSTRING, PUSHORT, PRXSTRING);
- int ExecuteMacro(char *, int);
- void PM_intc_cleanup();
- void PM_setup();
- #endif /* OS2 */
-
- #if defined(ATARI) || defined(MTOS)
- /* For findfile () (?) */
- # include <support.h>
- void appl_exit(void);
- void MTOS_open_pipe(void);
- extern int aesid;
- #endif
-
- RETSIGTYPE inter(anint)
- int anint;
- {
- #ifdef OS2
- (void) signal(anint, SIG_ACK);
- #else
- (void) signal(SIGINT, (sigfunc) inter);
- #endif
-
- #ifndef DOSX286
- (void) signal(SIGFPE, SIG_DFL); /* turn off FPE trapping */
- #endif
- #ifdef OS2
- PM_intc_cleanup();
- #else
- term_reset();
- (void) putc('\n', stderr);
- longjmp(command_line_env, TRUE); /* return to prompt */
- #endif
- }
-
- #ifdef LINUXVGA
- /* utility functions to ensure that setuid gnuplot
- * assumes root privileges only for those parts
- * of the code which require root rights.
- *
- * By "Dr. Werner Fink" <werner@suse.de>
- */
- static uid_t euid, ruid;
- static gid_t egid, rgid;
- static int asked_privi = 0;
-
- void
- drop_privilege()
- {
- if (!asked_privi) {
- euid = geteuid();
- egid = getegid();
- ruid = getuid();
- rgid = getgid();
- asked_privi = 1;
- }
- if (setegid(rgid) == -1)
- (void) fprintf(stderr, "setegid(%d): %s\n",
- (int) rgid, strerror(errno));
- if (seteuid(ruid) == -1)
- (void) fprintf(stderr, "seteuid(%d): %s\n",
- (int) ruid, strerror(errno));
- }
-
- void
- take_privilege()
- {
- if (!asked_privi) {
- euid = geteuid();
- egid = getegid();
- ruid = getuid();
- rgid = getgid();
- asked_privi = 1;
- }
- if (setegid(egid) == -1)
- (void) fprintf(stderr, "setegid(%d): %s\n",
- (int) egid, strerror(errno));
- if (seteuid(euid) == -1)
- (void) fprintf(stderr, "seteuid(%d): %s\n",
- (int) euid, strerror(errno));
- }
- #endif /* LINUXVGA */
-
-
- /* a wrapper for longjmp so we can keep everything local */
- void bail_to_command_line()
- {
- longjmp(command_line_env, TRUE);
- }
-
- #if defined(_Windows) || defined(_Macintosh)
- int gnu_main(argc, argv)
- #else
- int main(argc, argv)
- #endif
- int argc;
- char **argv;
- {
- #ifdef LINUXVGA
- LINUX_setup();
- #endif
- /* make sure that we really have revoked root access, this might happen if
- gnuplot is compiled without vga support but is installed suid by mistake */
- #ifdef __linux__
- setuid(getuid());
- #endif
- #if defined(MSDOS) && !defined(_Windows) && !defined(__GNUC__)
- PC_setup();
- #endif /* MSDOS !Windows */
- /* HBB: Seems this isn't needed any more for DJGPP V2? */
- /* HBB: disable all floating point exceptions, just keep running... */
- #if defined(DJGPP) && (DJGPP!=2)
- _control87(MCW_EM, MCW_EM);
- #endif
-
- #if defined(OS2)
- int rc;
- if (_osmode == OS2_MODE) {
- PM_setup();
- rc = RexxRegisterSubcomExe("GNUPLOT", (PFN) RexxInterface, NULL);
- }
- #endif
-
- /* malloc large blocks, otherwise problems with fragmented mem */
- #ifdef OSK
- _mallocmin(102400);
- #endif
-
- #ifdef MALLOCDEBUG
- malloc_debug(7);
- #endif
-
- /* get helpfile from home directory */
- #ifndef DOSX286
- # ifndef _Windows
- # if defined (__TURBOC__) && (defined (MSDOS) || defined(DOS386))
- strcpy(HelpFile, argv[0]);
- strcpy(strrchr(HelpFile, DIRSEP1), "\\gnuplot.gih");
- # endif /* - DJL */
- # endif /* !_Windows */
- #endif /* !DOSX286 */
- #ifdef __DJGPP__
- {
- char *s;
- strcpy(HelpFile, argv[0]);
- for (s = HelpFile; *s; s++)
- if (*s == DIRSEP1)
- *s = DIRSEP2; /* '\\' to '/' */
- strcpy(strrchr(HelpFile, DIRSEP2), "/gnuplot.gih");
- } /* Add also some "paranoid" tests for '\\': AP */
- #endif /* DJGPP */
-
- #ifdef VMS
- unsigned int status[2] = { 1, 0 };
- #endif
-
- #ifdef HAVE_LIBREADLINE
- rl_readline_name = argv[0];
- rl_complete_with_tilde_expansion = 1;
- #endif
-
- #ifdef X11
- {
- int n = X11_args(argc, argv);
- argv += n;
- argc -= n;
- }
- #endif
-
- #ifdef apollo
- apollo_pfm_catch();
- #endif
-
- /* moved to ATARI_init in atariaes.trm */
- /* #ifdef ATARI
- void application_init(void);
- application_init();
- #endif */
-
- #ifdef MTOS
- MTOS_open_pipe();
- #endif
-
- setbuf(stderr, (char *) NULL);
-
- #ifndef NO_SETVBUF
- /* this was once setlinebuf(). Docs say this is
- * identical to setvbuf(,NULL,_IOLBF,0), but MS C
- * faults this (size out of range), so we try with
- * size of 1024 instead. [SAS/C does that, too. -lh]
- * Failing this, I propose we just make the call and
- * ignore the return : its probably not a big deal
- */
- if (setvbuf(stdout, (char *) NULL, _IOLBF, (size_t) 1024) != 0)
- fputs("Could not linebuffer stdout\n", stderr);
- #endif
-
- gpoutfile = stdout;
- (void) Gcomplex(&udv_pi.udv_value, Pi, 0.0);
-
- init_memory();
-
- interactive = FALSE;
- init_terminal(); /* can set term type if it likes */
-
- #ifdef AMIGA_SC_6_1
- if (IsInteractive(Input()) == DOSTRUE)
- interactive = TRUE;
- else
- interactive = FALSE;
- #else
- # if (defined(__MSC__) && defined(_Windows)) || defined(__WIN32__)
- interactive = TRUE;
- # else
- interactive = isatty(fileno(stdin));
- # endif
- #endif /* !AMIGA_SC_6_1 */
-
- if (argc > 1)
- interactive = noinputfiles = FALSE;
- else
- noinputfiles = TRUE;
-
- if (interactive)
- show_version(stderr);
-
- #ifdef VMS
- /* initialise screen management routines for command recall */
- if (status[1] = smg$create_virtual_keyboard(&vms_vkid) != SS$_NORMAL)
- done(status[1]);
- if (status[1] = smg$create_key_table(&vms_ktid) != SS$_NORMAL)
- done(status[1]);
- #endif /* VMS */
-
- if (!setjmp(command_line_env)) {
- /* first time */
- interrupt_setup();
- load_rcfile();
- init_fit(); /* Initialization of fitting module */
-
- if (interactive && term != 0) /* not unknown */
- fprintf(stderr, "\nTerminal type set to '%s'\n", term->name);
- } else {
- /* come back here from int_error() */
- if (interactive == FALSE)
- exit_status = EXIT_FAILURE;
-
- #ifdef AMIGA_SC_6_1
- (void) rawcon(0);
- #endif
- load_file_error(); /* if we were in load_file(), cleanup */
- #ifdef _Windows
- SetCursor(LoadCursor((HINSTANCE) NULL, IDC_ARROW));
- #endif
-
- #ifdef VMS
- /* after catching interrupt */
- /* VAX stuffs up stdout on SIGINT while writing to stdout,
- so reopen stdout. */
- if (gpoutfile == stdout) {
- if ((stdout = freopen("SYS$OUTPUT", "w", stdout)) == NULL) {
- /* couldn't reopen it so try opening it instead */
- if ((stdout = fopen("SYS$OUTPUT", "w")) == NULL) {
- /* don't use int_error here - causes infinite loop! */
- fputs("Error opening SYS$OUTPUT as stdout\n", stderr);
- }
- }
- gpoutfile = stdout;
- }
- #endif /* VMS */
- if (!interactive && !noinputfiles) {
- term_reset();
- #if defined(ATARI) || defined(MTOS)
- if (aesid > -1)
- atexit(appl_exit);
- #endif
- return (IO_ERROR); /* exit on non-interactive error */
- }
- }
-
- if (argc > 1) {
- #ifdef _Windows
- int noend = 0;
- #endif
-
- /* load filenames given as arguments */
- while (--argc > 0) {
- ++argv;
- c_token = NO_CARET; /* in case of file not found */
- #ifdef _Windows
- if (stricmp(*argv, "-noend") == 0 || stricmp(*argv, "/noend") == 0)
- noend = 1;
- else
- #endif
- if (strcmp(*argv, "-") == 0) {
- /* DBT 10-7-98 go interactive if "-" on command line */
-
- interactive = TRUE;
- /* will this work on all platforms? */
-
- while (!com_line());
-
- /* interactive = FALSE; */ /* should this be here? */
-
- } else
- load_file(fopen(*argv, "r"), *argv, FALSE);
- }
- #ifdef _Windows
- if (noend) {
- interactive = TRUE;
- while (!com_line());
- }
- #endif
- } else {
- /* take commands from stdin */
- while (!com_line());
- }
-
- term_reset();
-
- #ifdef OS2
- if (_osmode == OS2_MODE)
- RexxDeregisterSubcom("GNUPLOT", NULL);
- #endif
-
- #if defined(ATARI) || defined(MTOS)
- if (aesid > -1)
- atexit(appl_exit);
- #endif
- return (exit_status);
- }
-
- #if (defined(ATARI) || defined(MTOS)) && defined(__PUREC__)
- int purec_matherr(struct exception *e)
- {
- char *c;
- switch (e->type) {
- case DOMAIN:
- c = "domain error";
- break;
- case SING:
- c = "argument singularity";
- break;
- case OVERFLOW:
- c = "overflow range";
- break;
- case UNDERFLOW:
- c = "underflow range";
- break;
- default:
- c = "(unknown error";
- break;
- }
- fprintf(stderr, "\
- math exception : %s\n\
- name : %s\n\
- arg 1: %e\n\
- arg 2: %e\n\
- ret : %e\n",
- c,
- e->name,
- e->arg1,
- e->arg2,
- e->retval);
-
- return 1;
- }
- #endif /* (ATARI || MTOS) && PUREC */
-
-
- /* Set up to catch interrupts */
- void interrupt_setup()
- {
- #ifdef __PUREC__
- setmatherr(purec_matherr);
- #endif
-
- (void) signal(SIGINT, (sigfunc) inter);
-
- #ifdef SIGPIPE
- /* ignore pipe errors, this might happen with set output "|head" */
- (void) signal(SIGPIPE, SIG_IGN);
- #endif /* SIGPIPE */
- }
-
-
- /* Look for a gnuplot init file in . or home directory */
- static void load_rcfile()
- {
- FILE *plotrc = NULL;
- char home[80];
- char rcfile[sizeof(PLOTRC) + 80];
- char *tmp_home = NULL;
- #ifndef VMS
- char *p; /* points to last char in home path, or to \0, if none */
-
- tmp_home = getenv(HOME);
- if (tmp_home) {
- safe_strncpy(home, tmp_home, sizeof(home));
- if (strlen(home))
- p = &home[strlen(home) - 1];
- else
- p = home;
- if ((*p != DIRSEP1) && (*p != DIRSEP2) && (*p != NUL)) {
- assert(p >= home && p <= (home + sizeof(home) - 1 - 2));
- if (*p)
- p++;
- *p++ = DIRSEP1;
- *p = NUL;
- }
- }
- #else /* VMS */
- safe_strncpy(home, HOME, sizeof(home));
- tmp_home = home;
- #endif /* VMS */
-
- #ifdef NOCWDRC
- /* inhibit check of init file in current directory for security reasons */
- #else
- (void) strcpy(rcfile, PLOTRC);
- plotrc = fopen(rcfile, "r");
- #endif /* !NOCWDRC */
-
- if (plotrc == NULL) {
- if (tmp_home) {
- (void) sprintf(rcfile, "%s%s", home, PLOTRC);
- plotrc = fopen(rcfile, "r");
- #if defined(ATARI) || defined(MTOS)
- if (plotrc == NULL) {
- char const *const ext[] = { NULL };
- char *ini_ptr = findfile(PLOTRC, getenv("GNUPLOTPATH"), ext);
-
- if (ini_ptr)
- plotrc = fopen(ini_ptr, "r");
- }
- #endif /* ATARI || MTOS */
- }
- }
- if (plotrc)
- load_file(plotrc, rcfile, FALSE);
- }
-
- #ifdef OS2
-
- int ExecuteMacro(char *argv, int namelength)
- {
- RXSTRING rxRc;
- RXSTRING rxArg;
- char pszName[CCHMAXPATH];
- short sRc;
- int rc;
-
- safe_strncpy(pszName, argv, sizeof(pszName));
- MAKERXSTRING(rxArg, argv, strlen(argv));
- rc = RexxStart(1,
- &rxArg,
- pszName,
- NULL,
- "GNUPLOT",
- RXCOMMAND,
- NULL,
- &sRc,
- &rxRc);
- if (rc == -4)
- rc = 0; /* run was cancelled-don't give error message */
-
- /* We don't use this value ?
- BTW, don't use free() instead since it's allocated inside RexxStart() */
- DosFreeMem(rxRc.strptr);
- return rc;
- }
-
- ULONG RexxInterface(PRXSTRING rxCmd, PUSHORT pusErr, PRXSTRING rxRc)
- /*
- ** Rexx command line interface
- */
- {
- int rc;
- static jmp_buf keepenv;
- int cmdlen;
-
- memcpy(keepenv, command_line_env, sizeof(jmp_buf));
- if (!setjmp(command_line_env)) {
- /* set variable input_line.
- * Watch out for line length of NOT_ZERO_TERMINATED strings ! */
- cmdlen = rxCmd->strlength + 1;
- safe_strncpy(input_line, rxCmd->strptr, cmdlen);
- input_line[cmdlen] = NUL;
-
- rc = do_line();
- *pusErr = RXSUBCOM_OK;
- rxRc->strptr[0] = rc + '0';
- rxRc->strptr[1] = NUL;
- rxRc->strlength = strlen(rxRc->strptr);
- } else {
- *pusErr = RXSUBCOM_ERROR;
- RexxSetHalt(getpid(), 1);
- }
- memcpy(command_line_env, keepenv, sizeof(jmp_buf));
- return 0;
- }
- #endif
-